#ifndef __BASIC__STORE_H__
#define __BASIC__STORE_H__

#include <cstdint>
#include <map>
#if defined(M_GLOBAL_DEBUG)
#include <iostream>
#endif

template <typename K, typename V>
class tpl_Store {
  using type_k = K;
  using type_pv = V*;
  using type_map = std::map<const type_k, type_pv>;
  using type_map_it = typename std::map<const type_k, type_pv>::iterator;
  using type = tpl_Store<K, V>;

public:
  tpl_Store(const tpl_Store&) = delete;
  tpl_Store(const tpl_Store&&) = delete;
  type& operator=(const type&) = delete;
  tpl_Store() = default;
  virtual ~tpl_Store() {
    m_map.clear();
  };

  inline bool Set(const type_k& key, type_pv value) noexcept {
    if (Has(key))
      return false;
    Set_d(key, value);
    return true;
  };

  inline void Set_d(const type_k& key, type_pv value) noexcept {
    m_map[key] = value;
  }

  inline type_pv Remove(const type_k& key) noexcept {
    if (Has(key)) {
      type_pv _tmp = m_map[key];
      m_map.erase(key);
      return _tmp;
    }
    return nullptr;
  };

  inline type_pv Get(const type_k& key) noexcept {
    if (Has(key)) {
      return m_map[key];
    }
    return nullptr;
  };

  inline const type_pv Get(const type_k& key) const noexcept {
    return m_map[key];
  };

  inline bool Has(const type_k& key) const noexcept {
    return m_map.find(key) != m_map.end();
  };

  inline void Clear() {
    m_map.clear();
  }

  inline std::int32_t GetSize() const noexcept {
    return m_map.size();
  }

  type_pv Traversal(bool begin) {
    if (begin) {
      m_map_it = m_map.begin();
      return m_map_it->second;
    } else {
      if (++m_map_it == m_map.end())
        return nullptr;
      return m_map_it->second;
    }
  }

#if defined(M_GLOBAL_DEBUG)
  void dbgPrintValueAddresses() {
    for (auto it = m_map.begin(); it != m_map.end(); ++it) {
      std::cout << "&m_map[" << it->first << "]=" << &(it->second) << "/"
                << it->second << std::endl;
    }
  }
#endif

private:
  type_map m_map;
  type_map_it m_map_it;
};

#endif
